package com.shiro.second.permitted.permission;

import com.alibaba.druid.util.StringUtils;
import junit.framework.Assert;

import java.io.Serializable;

import org.apache.shiro.authz.Permission;

/**
 *  规则
 *    +资源字符串+权限位+实例ID
 *
 *  以+开头 中间通过+分割
 *
 *  权限：
 *     0 表示所有权限
 *     1 新增 0001
 *     2 修改 0010
 *     4 删除 0100
 *     8 查看 1000
 *
 *  如 +user+10 表示对资源user拥有修改/查看权限
 *	权限位的第二个+必须是紧跟数字，否则抛 NumberFormatException(学习者tqw初充)	
 *
 *  不考虑一些异常情况
 *  
 *
 * <p>User: Zhang Kaitao
 * <p>Date: 14-1-26
 * <p>Version: 1.0
 * 
 */
public class BitPermission implements Permission,Serializable{
	private static final long serialVersionUID = 1L;
	
	private String resourceIdentify;//资源字符串,默认为*,根据implies判断，即有资源权限
    private int permissionBit;//权限位。默认为0，表示有对所资源的操作权限
    private String instanceId;//实例ID,默认为*,表示有对所实例的操作权限
    
    public BitPermission(String permissionString) {
        String[] array = permissionString.split("\\+");

        if(array.length > 1) {
            resourceIdentify = array[1];
        }

        if(StringUtils.isEmpty(resourceIdentify)) {
            resourceIdentify = "*";
        }

        if(array.length > 2) {
            permissionBit = Integer.valueOf(array[2]);
        }

        if(array.length > 3) {
            instanceId = array[3];
        }

        if(StringUtils.isEmpty(instanceId)) {
            instanceId = "*";
        }

    }
    
    public boolean implies(Permission p) {
        if(!(p instanceof BitPermission)) {
            return false;
        }
        BitPermission other = (BitPermission) p;
        //如果资源id为*或者验证者资源id完全一致，表示捅有资源权限
        if(	!( "*".equals(this.resourceIdentify) || this.resourceIdentify.equals(other.resourceIdentify)) ) {
            return false;
        }
        //如果权限为0表示捅有所有权限。或者权限完全一致，则表示有资源操作权限.(由于前面有权限为0的判断。所以权限一致时，不可能为0)
        if(!(this.permissionBit ==0 || (this.permissionBit & other.permissionBit) != 0)) {
            return false;
        }
        //如果实例id为*号。或者验证者实例id完全一致，则不返回false.表示捅有实例的操作权限。
        if(!("*".equals(this.instanceId) || this.instanceId.equals(other.instanceId))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "BitPermission{" +
                "resourceIdentify='" + resourceIdentify + '\'' +
                ", permissionBit=" + permissionBit +
                ", instanceId='" + instanceId + '\'' +
                '}';
    }
}
